package com.xmut.mall.ware.service.impl;

import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.xmut.mall.ware.entity.WareOrderTaskDetailEntity;
import com.xmut.mall.ware.entity.WareOrderTaskEntity;
import com.xmut.mall.ware.feign.OrderFeignService;
import com.xmut.mall.ware.feign.ProductFeignService;
import com.xmut.mall.ware.service.WareOrderTaskDetailService;
import com.xmut.mall.ware.service.WareOrderTaskService;
import com.xmut.mall.ware.to.SkuHasStockVo;
import com.xmut.mall.ware.utils.R;
import com.xmut.mall.ware.utils.RespBean;
import com.xmut.mall.ware.vo.EditSkuStockVo;
import com.xmut.mall.ware.vo.OrderEntityVo;
import com.xmut.mall.ware.vo.OrderItemEntityVo;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xmut.mall.ware.utils.PageUtils;
import com.xmut.mall.ware.utils.Query;

import com.xmut.mall.ware.dao.WareSkuDao;
import com.xmut.mall.ware.entity.WareSkuEntity;
import com.xmut.mall.ware.service.WareSkuService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;


@Service("wareSkuService")
public class WareSkuServiceImpl extends ServiceImpl<WareSkuDao, WareSkuEntity> implements WareSkuService {

    @Autowired
    private WareSkuDao wareSkuDao;

    @Autowired
    private ProductFeignService productFeignService;

    @Autowired
    private WareOrderTaskService wareOrderTaskService;

    @Autowired
    private WareOrderTaskDetailService wareOrderTaskDetailService;

    @Autowired
    private OrderFeignService orderFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        QueryWrapper<WareSkuEntity> wrapper = new QueryWrapper<>();
        String skuId = (String) params.get("skuId");
        if (!StringUtils.isEmpty(skuId)) {
            wrapper.eq("sku_id", skuId);
        }

        String wareId = (String) params.get("wareId");
        if (!StringUtils.isEmpty(wareId)) {
            wrapper.eq("ware_id", wareId);
        }

        IPage<WareSkuEntity> page = this.page(
                new Query<WareSkuEntity>().getPage(params), wrapper
        );

        return new PageUtils(page);
    }

    @Override
    public void addStock(Long skuId, Long wareId, Integer skuNum) {
        //1、判断如果还没有这个库存记录新增
        List<WareSkuEntity> entities = wareSkuDao.selectList(new QueryWrapper<WareSkuEntity>().eq("sku_id", skuId).eq("ware_id", wareId));
        if (entities == null || entities.size() == 0) {
            WareSkuEntity skuEntity = new WareSkuEntity();
            skuEntity.setSkuId(skuId);
            skuEntity.setStock(skuNum);
            skuEntity.setWareId(wareId);
            skuEntity.setStockLocked(0);
            //TODO 远程查询sku的名字，如果失败，整个事务无需回滚
            //1、自己catch异常
            //TODO 还可以用什么办法让异常出现以后不回滚？高级
            try {
                R info = productFeignService.info(skuId);
                Map<String, Object> data = (Map<String, Object>) info.get("skuInfo");

                if (info.getCode() == 0) {
                    skuEntity.setSkuName((String) data.get("skuName"));
                }
            } catch (Exception e) {

            }


            wareSkuDao.insert(skuEntity);
        } else {
            wareSkuDao.addStock(skuId, wareId, skuNum);
        }

    }

    /**
     * 查看该sku对应的商品是否还有库存
     *
     * @param skuIds
     * @return
     */
    @Override
    public List<SkuHasStockVo> getSkusHasStock(List<Long> skuIds) {
        List<SkuHasStockVo> collect = skuIds.stream().map(skuId -> {
            SkuHasStockVo vo = new SkuHasStockVo();
            // 查询当前sku的总库存量
            Long count = baseMapper.getSkuStock(skuId);
            vo.setSkuId(skuId);
            vo.setHasStock(count == null ? false : count > 0);
            return vo;
        }).collect(Collectors.toList());
        return collect;
    }

    /**
     * 添加商品的时候生成库存信息
     *
     * @param list
     * @return
     */
    @Override
    public RespBean generateSkuWare(List<WareSkuEntity> list) {
        Boolean result = this.saveBatch(list);
        if (result) {
            return RespBean.success("操作成功");
        } else {
            return RespBean.error("操作失败");
        }
    }

    /**
     * 获取Sku的库存
     *
     * @param spuId
     * @return
     */
    @Override
    public RespBean getSkuWare(Long spuId) {
        List<WareSkuEntity> wareSku = this.list(new QueryWrapper<WareSkuEntity>().eq("spu_id", spuId));
        return RespBean.success("获取成功", wareSku);
    }

    /**
     * 修改sku的库存
     *
     * @param params
     * @return
     */
    @Override
    public RespBean editSkuWare(Map<String, Object> params) {
        Long skuId = Long.parseLong(params.get("skuId").toString());
        Integer skuStock = Integer.parseInt(params.get("skuStock").toString());

        boolean update = this.update(new UpdateWrapper<WareSkuEntity>().set("stock", skuStock).eq("sku_id", skuId));
        if (update) {
            return RespBean.success("修改库存成功");
        } else {
            return RespBean.error("修改库存失败");
        }
    }

    /**
     * 获取sku的库存详情
     *
     * @param skuId
     * @return
     */
    @Override
    public RespBean getSkuWareNumber(Long skuId) {
        Integer stock = this.baseMapper.getSkuWareNumber(skuId);

        return RespBean.success("获取成功", stock);
    }

    /**
     * 修改sku的库存
     *
     * @param vo
     * @return
     */
    @Override
    public RespBean editSkuStock(EditSkuStockVo vo) {
        boolean update = this.update(new UpdateWrapper<WareSkuEntity>().set("stock", vo.getStock())
                .eq("sku_id", vo.getSkuId()));

        if (update) {
            return RespBean.success("修改库存成功");
        } else {
            return RespBean.error("修改库存失败");
        }

    }

    /**
     * 获取spu的库存情况
     *
     * @param spuId
     * @return
     */
    @Override
    public RespBean getSpuStock(Long spuId) {
        List<WareSkuEntity> wareList = this.list(new QueryWrapper<WareSkuEntity>().eq("spu_id", spuId));

        Map<Long, Boolean> spuStock = wareList.stream().collect(Collectors.toMap(WareSkuEntity::getSkuId, value -> {
            Boolean result = new Boolean(false);
            if (value.getStock() != null && value.getStock() > 0) {
                result = true;
            }
            return result;
        }));

        return RespBean.success("获取成功", spuStock);
    }

    /**
     * 根据订单项锁商品库存
     *
     * @param entity
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public RespBean lockStock(OrderItemEntityVo entity) {
        // 查找父工作单
        WareOrderTaskEntity wareOrderTaskEntity = wareOrderTaskService.getOne(new QueryWrapper<WareOrderTaskEntity>().eq("order_sn", entity.getOrderSn()));

        WareOrderTaskDetailEntity wareOrderTaskDetailEntity = new WareOrderTaskDetailEntity();
        wareOrderTaskDetailEntity.setTaskId(wareOrderTaskEntity.getId());
        wareOrderTaskDetailEntity.setSkuId(entity.getSkuId());
        wareOrderTaskDetailEntity.setSkuName(entity.getGoodsName());
        wareOrderTaskDetailEntity.setSkuNum(entity.getNum());
        wareOrderTaskDetailEntity.setOrderSn(entity.getOrderSn());
        wareOrderTaskDetailEntity.setLockStatus(1);

        // 保存工作单
        boolean wareOrderTaskDetailEntitySave = wareOrderTaskDetailService.save(wareOrderTaskDetailEntity);

        // 修改库存表的库存内容
        WareSkuEntity skuWare = this.getOne(new QueryWrapper<WareSkuEntity>().eq("sku_id", entity.getSkuId()));
        Integer nowStock = skuWare.getStock() - entity.getNum(); // 现在的库存数量
        Integer nowLock = skuWare.getStockLocked() + entity.getNum();
        // 进行修改
        boolean stockLock = this.update(new UpdateWrapper<WareSkuEntity>()
                .set("stock", nowStock)
                .set("stock_locked", nowLock)
                .eq("sku_id", entity.getSkuId()));

        if (wareOrderTaskDetailEntitySave && stockLock) {
            return RespBean.success("库存锁定成功");
        } else {
            return RespBean.error("库存锁定失败");
        }
    }

    /**
     * 保存订单时修改锁库存工作单
     *
     * @param entity
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public RespBean updateLockStockTask(OrderEntityVo entity) {
        boolean updateWareOrderTask = wareOrderTaskService.update(new UpdateWrapper<WareOrderTaskEntity>()
                .set("consignee", entity.getConsigneeName())
                .set("consignee_tel", entity.getConsigneeMobile())
                .set("delivery_address", entity.getConsigneeDetail())
                .set("order_comment", entity.getRemark())
                .eq("order_sn", entity.getSn()));
        if (updateWareOrderTask) {
            return RespBean.success("修改成功");
        } else {
            return RespBean.error("修改失败");
        }

    }

    /**
     * 解锁库存 并且修改订单状态
     *
     * @param params
     * @return
     */
    @Override
    public void unLockStock(Map<String, Object> params) {
        String orderSN = MapUtil.getStr(params, "orderSN");

        // 根据sn查询工单
        WareOrderTaskEntity wareOrderTaskEntity = wareOrderTaskService.getOne(new QueryWrapper<WareOrderTaskEntity>()
                .eq("order_sn", orderSN));
        // 防止空指针异常
        if (wareOrderTaskEntity == null) {
            wareOrderTaskEntity = new WareOrderTaskEntity();
        }

        boolean updateOrderTask = false;
        if (wareOrderTaskEntity.getTaskStatus() == 1) {
            boolean updateWareOrderTaskDetail = false;
            // 如果当前工单的状态为被锁定 那就继续处理
            // 查询工单详情
            List<WareOrderTaskDetailEntity> detailList = wareOrderTaskDetailService
                    .list(new QueryWrapper<WareOrderTaskDetailEntity>()
                            .eq("order_sn", orderSN));

            for (WareOrderTaskDetailEntity entity : detailList) {
                if (entity.getLockStatus() == 1) {
                    // 如果当前工单详情的状态为被锁定 那就进行解锁
                    WareSkuEntity wareSkuEntity = this.getOne(new QueryWrapper<WareSkuEntity>()
                            .eq("sku_id", entity.getSkuId()));
                    // 计算库存中被锁数量
                    Integer stockLock = wareSkuEntity.getStockLocked() - entity.getSkuNum();
                    // 计算当前库存数量
                    Integer stockNum = wareSkuEntity.getStock() + entity.getSkuNum();
                    if (stockLock <= 0) {
                        stockLock = 0;
                    }
                    if (stockNum <= 0) {
                        stockNum = 0;
                    }
                    // 修改库存数量
                    System.out.println("修改库存数量" + stockLock + "  " + stockNum);
                    boolean updateWareSku = this.update(new UpdateWrapper<WareSkuEntity>()
                            .set("stock", stockNum)
                            .set("stock_locked", stockLock)
                            .eq("sku_id", entity.getSkuId()));
                    // 如果库存修改成功 修改当前工单详情
                    if (updateWareSku) {
                        System.out.println("修改工单详情");
                        updateWareOrderTaskDetail = wareOrderTaskDetailService.update(new UpdateWrapper<WareOrderTaskDetailEntity>()
                                .set("lock_status", 2)
                                .eq("order_sn", orderSN));
                    }
                }
            }
            // 如果工单的详情被解锁 工单本体也解锁
            if (updateWareOrderTaskDetail) {
                System.out.println("修改工单");
                updateOrderTask = wareOrderTaskService.update(new UpdateWrapper<WareOrderTaskEntity>()
                        .set("task_status", 2)
                        .eq("order_sn", orderSN));
            }
        }

        // 如果工单详情被修改 那就把订单详情一起修改
        if (updateOrderTask) {
            // 发送mq修改订单状态
            DefaultMQProducer producer = new DefaultMQProducer("cancelgroup");
            producer.setNamesrvAddr("192.168.253.128:9876");
            try {
                producer.start();
                Message message = new Message();
                params.put("Reason", "订单超时未支付");
                message.setBody(JSON.toJSONString(params).getBytes(StandardCharsets.UTF_8));
                message.setTopic("CancelOrderTopic");
                SendResult send = producer.send(message);
                System.out.println("取消订单信息发送结果:" + send.getSendStatus());
            } catch (MQClientException e) {
                e.printStackTrace();
            } catch (MQBrokerException e) {
                e.printStackTrace();
            } catch (RemotingException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                try {
                    producer.shutdown();
                    System.out.println("链接已关闭");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * 创建锁库存工单
     *
     * @param entity
     * @return
     */
    @Override
    public RespBean createWareOrderTask(OrderEntityVo entity) {
        WareOrderTaskEntity wareOrderTask = new WareOrderTaskEntity();
        wareOrderTask.setOrderSn(entity.getSn());
        wareOrderTask.setTaskStatus(1);// 激活状态
        wareOrderTask.setConsignee(entity.getConsigneeName());
        wareOrderTask.setConsigneeTel(entity.getConsigneeMobile());
        wareOrderTask.setDeliveryAddress(entity.getConsigneeDetail());
        wareOrderTask.setOrderComment(entity.getRemark());
        wareOrderTask.setCreateTime(new Date());

        boolean save = wareOrderTaskService.save(wareOrderTask);
        if (save) {
            return RespBean.success("创建库存工作单成功");
        } else {
            return RespBean.error("创建库存工作单失败");
        }
    }

    /**
     * 当订单被支付时解锁库存
     *
     * @param param
     * @return
     */
    @Override
    public RespBean unLockStockWhenOrderPayed(Map<String, Object> param) {
        String orderSN = MapUtil.getStr(param, "orderSN");

        // 根据SN获取工单
        List<WareOrderTaskEntity> taskList = wareOrderTaskService.list(new QueryWrapper<WareOrderTaskEntity>()
                .eq("order_sn", orderSN));

        boolean result = false;

        for (WareOrderTaskEntity wareOrderTask : taskList) {
            // 搜索工单详情
            List<WareOrderTaskDetailEntity> detailList = wareOrderTaskDetailService
                    .list(new QueryWrapper<WareOrderTaskDetailEntity>()
                            .eq("task_id", wareOrderTask.getId()));
            for (WareOrderTaskDetailEntity wareOrderTaskDetailEntity : detailList) {
                // 修改详情
                // 查询对应sku
                WareSkuEntity wareSkuEntity = wareSkuDao.selectOne(new QueryWrapper<WareSkuEntity>()
                        .eq("sku_id", wareOrderTaskDetailEntity.getSkuId()));

                // 计算当前sku的库存
                Integer nowStock = wareSkuEntity.getStock() + wareOrderTaskDetailEntity.getSkuNum();

                // 计算sku当前被锁库存
                Integer nowLock = wareSkuEntity.getStockLocked() - wareOrderTaskDetailEntity.getSkuNum();
                if (nowLock <= 0) {
                    nowLock = 0;
                }
                // 修改库存表
                result = this.update(new UpdateWrapper<WareSkuEntity>()
                        .set("stock_locked", nowLock)
                        .set("stock", nowStock)
                        .eq("sku_id", wareOrderTaskDetailEntity.getSkuId()));
            }
            // 工单修改详情
            wareOrderTaskDetailService.update(new UpdateWrapper<WareOrderTaskDetailEntity>()
                    .set("lock_status", 3)
                    .eq("order_sn", orderSN));
            // 修改工单
            wareOrderTaskService.update(new UpdateWrapper<WareOrderTaskEntity>()
                    .set("task_status", 3)
                    .eq("order_sn", orderSN));
        }

        if (result) {
            return RespBean.success("库存扣减成功");
        } else {
            return RespBean.error("库存扣减失败");
        }

    }


}